BigQuery スキャン量減らす
読まれる = 課金対象のスキャンされる の意
WITH で定義したやつは評価されるまでスキャンされない
? RECURSIVE は?
パーティショニング
View に対しても効く
効かない場合もある気がする...
サブクエリでも効く
パーティショニングが効いたサブクエリを含む View にクエリした場合は効かない?
説: クエリから静的に解決できるものはスキャン量が減る
コンソール上の見積もり
https://gyazo.com/756c5ee2a3e1a4d5f933414ef4e8d23d
クラスタリングカラムが設定されていて使えるとこれより減る
? MERGE ... USING(ここ) に WITH 書いた時なんか扱いが変わる??
ここ だけスキャンした時となんか全然違うなー
WITH をほぐしても変わらなそう、USING の中の問題
深くて実行計画が変わるとか
静的に解決できる例
code:skip.sql
WITH params AS (
SELECT FALSE AS skip
)
SELECT
*
FROM
large_table, params
WHERE params.skip
これは 0B になる
code:skip2.sql
WITH params AS (
SELECT CURRENT_TIMESTAMP() <= "2023-03-08 00:00:00" AS skip
)
SELECT
*
FROM
large_table, params
WHERE params.skip
これも 0B (2023/3/8 16:17)
CURRENT_TIMESTAMP() を評価しないとわからないはずだけどうまくいく
SELECT EXTRACT(MINUTE FROM CURRENT_TIMESTAMP()) < 30 AS skip なども上手く働く
静的に解決するもの、とはまた違う → テーブルにアクセスせず実行可能なもの と言い換えるほうがよい?
code:empty.sql
WITH params AS (
SELECT MAX(id) IS NOT NULL AS skip FROM empty -- FALSE
)
SELECT
*
FROM
large_table, params
WHERE params.skip -- 常に FALSE
これも常に読まれる(要確認)
でも Scripting にしたら読まれない
code:scripting.sql
DECLARE skip BOOLEAN DEFAULT(
SELECT MAX(id) IS NOT NULL AS skip FROM pokutuna-playground.gomibako.empty
);
SELECT
*
FROM
large_table
WHERE
skip
段階的に実行されて解決されるから
code:where.sql
SELECT
*
FROM
large_table
WHERE
CURRENT_TIMESTAMP() < created -- これを満たす行は無い
でもこれはダメ(要確認、View かも)
declare と変数の値の代入を明示的に分けるように記述することを試してみたところ、定数として判定され、パーティションのプルーニングがうまく効くようになりました
これほんとかな? SET はその場で明に実行して値が設定されるけど、DEFAULT (...) は参照時まで評価が遅延されて... みたいなこと起きるのかな?
? あとでじっけんする
? SCRIPTING の途中の結果みたいときどうするのがよい?